package com.example.stmp.pojo;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.example.stmp.excel.ExcelListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class Tool {
    public static String encryption(String password) {
        StringBuilder binaryBuilder = new StringBuilder();

        // 将每个字符转换为二进制，并确保每个字符的二进制表示为8位，不足部分用01交替补足
        for (char c : password.toCharArray()) {
            String binary = Integer.toBinaryString(c); // 转换为二进制
            while (binary.length() < 8) {
                binary = binary + (binary.length() % 2 == 0 ? '0' : '1'); // 01交替补足
            }
            binaryBuilder.append(binary);
        }

        // 补足到160位，不足部分用01交替补足
        while (binaryBuilder.length() < 160) {
            binaryBuilder.append(binaryBuilder.length() % 2 == 0 ? '0' : '1');
        }

        // 将补足后的二进制字符串转换为七进制
        StringBuilder sevenBaseBuilder = new StringBuilder();
        for (Integer i = 0; i < binaryBuilder.length(); i += 10) {
            String binaryGroup = binaryBuilder.substring(i, Math.min(i + 10, binaryBuilder.length()));
            Integer decimalValue = Integer.parseInt(binaryGroup, 2); // 将二进制转换为十进制
            String sevenBaseValue = Integer.toString(decimalValue, 7); // 将十进制转换为七进制
            sevenBaseBuilder.append(sevenBaseValue); // 直接拼接七进制结果
        }

        return sevenBaseBuilder.toString(); // 返回最终的七进制字符串
    }

    public static String ceareNowTime(){
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();

        // 定义时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yy-MM-dd HH:mm:ss");

        // 格式化当前时间
        String formattedTime = now.format(formatter);

        return formattedTime;
    }
    public static <T> T getParameterType(Object value, Class<T> targetType) {
        if (value != null) {
            if (targetType == String.class) {
                return (T) value.toString();
            } else if (targetType == Integer.class || targetType == int.class) {
                return (T) Integer.valueOf((Integer) value);
            } else {
                // 其他类型直接返回
                return (T) value;
            }
        } else {
            return null;
        }
    }
    /**
     * 读取Excel文件内容
     * @param file Excel文件
     * @param head 数据模型类
     * @param <T> 泛型
     * @return 读取到的数据列表
     */
    public static <T> List<T> readExcel(MultipartFile file, Class<T> head) throws IOException {
        ExcelListener<T> excelListener = new ExcelListener<>();
        EasyExcel.read(file.getInputStream(), head, excelListener).sheet().doRead();
        return excelListener.getCachedDataList();
    }

    /**
     * 写入Excel
     *
     * @param list       由实体类的对象组成的List
     * @param parentPath 存放Excel的父路径（文件夹）
     * @param clazz      实体类的字节码对象
     * @return 导出路径或者null
     */
    public static <T> String writeExcel(List<?> list, String parentPath, Class<T> clazz) {
        String name = clazz.getSimpleName();
        return writeExcel(list, parentPath, name, clazz);
    }
    /**
     * 写入Excel
     *
     * @param list       由实体类的对象组成的List
     * @param parentPath 存放Excel的父路径（文件夹）
     * @param fileName   文件名
     * @param clazz      实体类的字节码对象
     * @return 导出路径或者null
     */
    public static <T> String writeExcel(List<?> list, String parentPath, String fileName, Class<T> clazz) {
        // 按照YYYYMMDDhhmmss的格式生成文件名
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String dateTime = formatter.format(LocalDateTime.now());
        File path = new File(parentPath, fileName + "_" + dateTime + ".xlsx");
        try {
            EasyExcel.write(path, clazz)
                    .sheet(fileName)
                    .doWrite(list);
            String absolutePath = path.getAbsolutePath();
            log.info("导出Excel成功，路径为：{}", absolutePath);
            return absolutePath;
        } catch (Exception e) {
            log.error("写出Excel失败", e);
            return null;
        }
    }

    /**
     * 将列表数据导出为Excel文件。
     *
     * @param list     待导出的数据列表，可以是任意类型。
     * @param response HTTP响应，用于将生成的Excel文件发送给客户端。
     * @param fileName 导出的Excel文件名，不包含后缀。建议使用英文名，以避免编码问题。
     * @param clazz    数据对象的类，用于指定Excel中的列与对象属性的映射关系。
     * @return 返回文件名，如果导出失败则返回null。
     * @throws UnsupportedEncodingException 如果字符编码不支持，则抛出此异常。
     * @throws IOException                  如果发生I/O错误，则抛出此异常。
     */
    public static <T> String writeExcel(List<?> list, HttpServletResponse response, String fileName, Class<T> clazz) throws UnsupportedEncodingException {

        // 按照YYYYMMDDhhmmss的格式生成文件名
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String dateTime = formatter.format(LocalDateTime.now());
        // 拼接文件名和时间戳后缀，并加上Excel文件的后缀
        fileName = fileName + "_" + dateTime + ".xlsx";

        // 设置响应头信息，指定响应类型为Excel文件，字符编码为UTF-8
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); // 设置响应类型为Excel文件
        response.setCharacterEncoding("utf-8");
        // 对文件名进行URL编码，以支持中文文件名，并将编码后的+号替换为%20
        fileName = URLEncoder
                .encode(fileName, "UTF-8")
                .replaceAll("\\+", "%20");
        // 设置响应头的Content-Disposition字段，指定文件名，浏览器将以此名下载文件
        response.setHeader("Content-disposition", "attachment;filename*=" + fileName);

        try {
            // 使用EasyExcel框架将列表数据写入到响应输出流中，指定Excel的样式和数据转换器
            EasyExcel.write(response.getOutputStream(), clazz)
                    .sheet(fileName)
                    .doWrite(list);
            // 记录日志，表示导出Excel成功
            String res = "filename*=" + fileName;
            log.info("导出Excel成功，文件 {} 已写入响应输出流", res);
            return res;
        } catch (Exception e) {
            // 记录日志，表示导出Excel失败
            log.error("写出Excel失败", e);
            return null;
        }
    }

    /**
     * 检查上传的文件是否为Excel文件。
     * <p>
     * 本方法通过检查文件的Content-Type（媒体类型）来判断上传的文件是否为Excel文件。
     * 它支持两种Excel文件类型：老式的xls格式和新式的xlsx格式。
     *
     * @param file 上传的文件对象
     * @return 如果文件是Excel文件，则返回true；否则返回false。
     */
    public static boolean isExcelFile(MultipartFile file) {
        // 获取上传文件的Content-Type
        String contentType = file.getContentType();

        // 判断Content-Type是否为Excel或CSV文件类型
        // 如果是Excel或CSV文件类型，则返回true
        return "application/vnd.ms-excel".equals(contentType) ||
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equals(contentType) ||
                "text/csv".equals(contentType);

        // 如果不是Excel或CSV文件类型，则返回false
    }
    // 判断字符串是否为空或空字符串
    public static boolean isNullOrEmpty(String string) {
        return string == null || string.trim().isEmpty();
    }

    //判断性别输入是否正确
    public static boolean validateGender(String gender) {
        if (gender == null) return false;
        return !gender.equals("1") && !gender.equals("2");
    }

    //判断一个字符串是否为空或全是空格
    public static boolean isBlank(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }
    /**
     * 读取Excel文件内容
     * @param file Excel文件
     * @param head 数据模型类
     * @param <T> 泛型
     * @return 读取到的数据列表
     */

}